
use crate::data_frame::{value::RealValue};
use crate::run_plan::window::{RunPlanExprWindow};
use crate::run_plan::func::{RunPlanExprFunc, RunPlanExprFuncComb};

//mod binary;
pub mod func;
pub mod accumulator;
pub mod window;
pub mod aggregation;

pub use window::logical_plan_window_to_run_plan;
use crate::physical_plan::window::window_group::WindowGroup;
use crate::data_frame::value::ElementValue;
use crate::data_frame::window::WindowElementDataInstance;
use crate::data_frame::single_data::SingleData;

pub enum RunPlanExpr {
    //Binary(Box<RunPlanPhysicalPlanFuncArg>,Box<PhysicalPlanExpr>,Box<RunPlanPhysicalPlanFuncArg>),
    Func(Box<RunPlanExprFunc>),
    FuncComb(Box<RunPlanExprFuncComb>),
    Window(Box<RunPlanExprWindow>)
}

pub struct RunPlanInstance{
    pub name: String,
    pub run_plan: Box<RunPlanExpr>,
}
impl RunPlanInstance{
    pub fn new(name: String, run_plan: Box<RunPlanExpr>)
        ->Box<RunPlanInstance>{

        return Box::new(RunPlanInstance{
            name: name,
            run_plan: run_plan,
        });
    }
    pub fn new_func(name: String, run_plan_func: Box<RunPlanExprFunc>) -> Box<RunPlanInstance>{
        return RunPlanInstance::new(name, Box::new(RunPlanExpr::Func(run_plan_func)));
    }
    pub fn new_func_comb(name: String, func_comb: Box<RunPlanExprFuncComb>)
        ->Box<RunPlanInstance>{
        return RunPlanInstance::new(name, Box::new(RunPlanExpr::FuncComb(func_comb)));
    }
    pub fn name(&self)->&str{
        return self.name.as_str();
    }
}

pub type HandResult = Result<RealValue,()>;

pub type HandResultList = Vec<HandResult>;
pub type WindowResult = Result<Option<WindowGroup<ElementValue,RealValue,WindowElementDataInstance>>,()>;
pub type AggregationResult = Result<Option<SingleData>,()>;

impl std::fmt::Debug for RunPlanExpr {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self{
            /*RunPlanExpr::Binary(left, op, right) => {
                f.debug_tuple("Filter")
                    .field(left)
                    .field(op)
                    .field(right)
                    .finish()
            },*/
            RunPlanExpr::Func(func) => {
                f.debug_tuple("Func")
                    .field(&func)
                    .finish()
            },
            RunPlanExpr::FuncComb(func_comb) => {
                f.debug_tuple("FuncComb")
                    .field(&func_comb)
                    .finish()
            },
            RunPlanExpr::Window(runplan_window) => {
                f.debug_struct("Window")
                    .finish()
            },
        }
    }
}



